#import "FoursquareManager.h"

// Shared instance of FoursquareManager
static FoursquareManager* sharedFoursquareManager = nil;

//  This Foursquare integration is possible thanks to the Foursquare API by
//  Eric Butler and associates.
//
//  Copyright (C) 2010 Eric Butler <eric@codebutler.com>

/**
 * A FoursquareManager is the main interface providing tools for all
 * Foursquare functionality supported by this application.
 *
 * Code used within this class and the supporting API was written by 
 * Eric Butler and other associates.
 *
 * The supporting API can be found in ./FourSquareAPI folder.
 *
 * @author      Eric Butler
 * @author      James Lin
 * @version     2.3.4 
 * @since       2.0.0
 */
@implementation FoursquareManager

/**
 * Retrieve the shared instance of the Foursquare manager.
 *
 * @return  the shared instance of FoursquareManager
 */
+ (FoursquareManager*)sharedFoursquareManager {
	@synchronized (self) {
		if (sharedFoursquareManager == nil) {
			sharedFoursquareManager = [[FoursquareManager alloc] init];
		}
		return sharedFoursquareManager;
	}
}

/**
 * Allocate the Foursquare manager.
 *
 * @return  the newly allocated shared instance of FoursquareManager
 */
+ (id) alloc {
	@synchronized (self) {
		sharedFoursquareManager = [super alloc];
		return sharedFoursquareManager;
	}
}

/**
 * Retrieve a copy of the Foursquare manager.
 *
 * @return  the shared instance of FoursquareManager
 */
+ (id) copy {
	@synchronized(self) {
		return sharedFoursquareManager;
	}
}

/**
 * Initialize the Foursquare manager.
 *
 * @return  the initialized FoursquareManager
 */
- (id)init {
    if ((self = [super init])) {
		// Create the venue check-in popup
		checkInPopup = [[UIAlertView alloc] initWithTitle:@""
												message:@"\n\n\n\n\n" 
											   delegate:self 
									  cancelButtonTitle:nil
									  otherButtonTitles:nil];
		CGFloat xCenter = 284 / 2;
		
		// Create the label for the venue check-in pop-up
		checkInLabel = [[UILabel alloc] initWithFrame:CGRectMake(xCenter-125, 10, 
																 250, 40)];
		checkInLabel.backgroundColor = [UIColor clearColor];
		checkInLabel.textAlignment = UITextAlignmentCenter;
		checkInLabel.lineBreakMode = UILineBreakModeWordWrap;
		checkInLabel.numberOfLines = 0;
		checkInLabel.font = [UIFont boldSystemFontOfSize:14.0];
		checkInLabel.textColor = [UIColor whiteColor];
		checkInLabel.text = @"";
		[checkInPopup addSubview:checkInLabel];
		
		// Create the text view for the venue check-in pop-up
		checkInTextView = [[UITextView alloc] initWithFrame:CGRectMake(xCenter-125, 60, 
																	   250, 65)];
		checkInTextView.keyboardAppearance = UIKeyboardAppearanceAlert;
		checkInTextView.delegate = self;
		checkInTextView.editable = YES;
		checkInTextView.returnKeyType = UIReturnKeyDone;
		checkInTextView.font = [UIFont systemFontOfSize:13.5];
		checkInTextView.backgroundColor = [UIColor whiteColor];
		checkInTextView.layer.borderColor = [[UIColor grayColor] CGColor];
		checkInTextView.layer.cornerRadius = 4;
		checkInTextView.layer.borderWidth = 1;
		checkInTextView.contentInset = UIEdgeInsetsMake(3, 7, 3, 7);
		[checkInPopup addSubview:checkInTextView];
		
		// Create a custom check in button for the venue check-in pop-up
		UIButton* checkInButton;
		checkInButton = [UIButton buttonWithType:UIButtonTypeCustom];
		[checkInButton addTarget:self 
						 action:@selector(attemptCheckIn)
			   forControlEvents:UIControlEventTouchUpInside];
		checkInButton.frame = CGRectMake(xCenter-127, 135, 127, 43);
		[checkInButton setBackgroundImage:[UIImage imageNamed:CHECKIN_BUTTON_IMAGE_FILENAME] 
								forState:UIControlStateNormal];
		[checkInPopup addSubview:checkInButton];
		
		// Create a custom cancel button for the venue check-in pop-up
		UIButton* cancelButton;
		cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
		[cancelButton addTarget:self 
						 action:@selector(dismissCheckIn)
			   forControlEvents:UIControlEventTouchUpInside];
		cancelButton.frame = CGRectMake(xCenter, 135, 127, 43);
		[cancelButton setBackgroundImage:[UIImage imageNamed:CANCEL_BUTTON_IMAGE_FILENAME] 
								forState:UIControlStateNormal];
		[checkInPopup addSubview:cancelButton];
		
		// Create the toolbar for specifying a location
		toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, VIEW_HEIGHT+44, 
															  VIEW_WIDTH, 44)];
		toolbar.barStyle = UIBarStyleBlack;
		locSelectorModeOn = NO;
    }
	
    return self;
}

/**
 * Set the Foursquare delegate.
 *
 * @param theDelegate  the delegate handling Foursquare events
 */
- (void)setDelegate:(id<FoursquareManagerDelegate>)theDelegate {
	delegate = theDelegate;
}

/**
 * Display the action sheet for Foursquare functionality given a tab bar.
 *
 * If the user is logged in, an action sheet will animate in using the 
 * tab bar as an origin.
 *
 * If the user is not logged in, a login pop-up will be presented instead.
 *
 * @param tabBar       the tab bar from which the Foursquare action sheet will appear
 * @param theDelegate  the delegate handling Foursquare manager events
 */
- (void)displayFromTabBar:(UITabBar*)tabBar 
			 withDelegate:(id<FoursquareManagerDelegate>)theDelegate {
	BOOL loggedIn = [FoursquareLogin sharedFoursquareLogin].isLoggedIn;
	parentTabBar = tabBar;
	delegate = theDelegate;
	
	NSString* signinTitle = loggedIn ? @"Sign out" : @"Sign in";
	UIActionSheet* foursquareActions = [UIActionSheet alloc];
	
	if (loggedIn) {
		[foursquareActions initWithTitle:@"\n" 
								delegate:self
					   cancelButtonTitle:@"Cancel"         // 5 (index)
				  destructiveButtonTitle:signinTitle       // 0
					   otherButtonTitles:@"View venues",   // 1
										 @"View tips",     // 2
									 	 @"View specials", // 3
										 @"Find friends",  // 4
										 nil];
	} else {
		[foursquareActions initWithTitle:@"\n" 
								delegate:self
					   cancelButtonTitle:@"Cancel"         // 5 (index)
				  destructiveButtonTitle:signinTitle       // 0
					   otherButtonTitles:@"View venues",   // 1
										 @"View tips",     // 2
										 @"View specials", // 3
										 nil];
	}
	
	[foursquareActions setTag:FoursquareActionTypeGeneral];
	
	UIImageView* poweredByHeader;
	poweredByHeader = [[UIImageView alloc] initWithImage:
					   [UIImage imageNamed:FOURSQUARE_REF_IMAGE]]; 
	[poweredByHeader setFrame:CGRectMake(VIEW_WIDTH/2-75, 10, 150, 24)];
	[foursquareActions addSubview:poweredByHeader];
	[poweredByHeader release];
	
	[foursquareActions showFromTabBar:tabBar];
	[foursquareActions release];
}

/**
 * Update the system with a fresh set of venue data.
 *
 * @param theDelegate  the delegate handling Foursquare manager events
 */
- (void)silentUpdateWithDelegate:(id<FoursquareManagerDelegate>)theDelegate {
	delegate = theDelegate;
	
	CLLocation* loc = [delegate getCurrentUserLocation];
	FoursquareVenueCollection* fsvc = [FoursquareVenueCollection sharedVenueCollection];
	
	[fsvc updateWithUserLocation:loc 
					 andDelegate:nil 
					  venueLimit:50 
					  identifier:VenueUpdateTypeNormal];
}

/**
 * Helper method to view the venues on the map.
 *
 * @param loc  the location to search
 */
- (void)viewVenuesAtLocation:(CLLocation*)loc {
	FoursquareVenueCollection* fsvc = [FoursquareVenueCollection sharedVenueCollection];
	
	NSString* msg = @"\nFinding venues\nPlease wait...";
	[GraphicsUtilities displayActivityIndicatorWithMsg:msg];
	
	[fsvc updateWithUserLocation:loc 
					 andDelegate:self 
					  venueLimit:[[MapAppSettings sharedSettings] foursquareVenueLimit] 
					  identifier:VenueUpdateTypeNormal];
}

/**
 * Handle a notification that the venue collection update has finished.
 *
 * @param identifier  the unique identifier for this update request
 * @see               FoursquareVenueCollectionDelegate
 */
- (void)handleVenueUpdateDoneWithIdentifier:(NSUInteger)identifier {
	FoursquareVenueCollection* fsvc = [FoursquareVenueCollection sharedVenueCollection];
	
	switch (identifier) {
		case VenueUpdateTypeNormal:
		{
			NSMutableArray* venues = [NSMutableArray array];
			
			for (FoursquareVenue* venue in [fsvc allVenues]) {
				FoursquareVenueAnnotation* ann = [FoursquareVenueAnnotation alloc];
				[ann initWithVenue:venue];
				
				[venues addObject:ann];
			}
			
			if ([venues count] > 0) {
				[delegate displayFoursquareAnnotations:venues];
			} else {
				[GraphicsUtilities displayAlertWithTitle:@"No venues found." 
												 message:nil];
			}
			
			[GraphicsUtilities hideActivityIndicator];
			break;
		}
		case VenueUpdateTypeView:
		{
			currentVenue = [fsvc findVenueWithNames:[viewDelegate getPossibleVenueNames]];
			//NSLog(@"venue is: %@", currentVenue.venueName);
			
			// Dismiss the status indicator
			if (foursquareIndicator) {
				[foursquareIndicator stopAnimating];
			}
			
			// Update the Foursquare button accordingly
			if ([FoursquareLogin sharedFoursquareLogin].isLoggedIn) {
				if (currentVenue != nil && [currentVenue.venueName length] > 0) {
					[foursquareButton setBackgroundImage:[UIImage imageNamed:FOURSQUARE_CHECKIN_IMAGE] 
												forState:UIControlStateNormal];
					[foursquareButton addTarget:self 
										 action:@selector(requestCheckIn) 
							   forControlEvents:UIControlEventTouchUpInside];
				} else {
					[foursquareButton setBackgroundImage:[UIImage imageNamed:FOURSQUARE_NOVENUE_IMAGE] 
												forState:UIControlStateNormal];
				}
			} else {
				[foursquareButton setBackgroundImage:[UIImage imageNamed:FOURSQUARE_LOGIN_IMAGE] 
											forState:UIControlStateNormal];
				[foursquareButton addTarget:self 
									 action:@selector(requestLogin) 
						   forControlEvents:UIControlEventTouchUpInside];
			}
			
			break;
		}
	}
}

/**
 * Helper method to view the venue tips on the map.
 *
 * @param loc  the location to search
 */
- (void)viewTipsAtLocation:(CLLocation*)loc {
	FoursquareTipCollection* ftvc = [FoursquareTipCollection sharedTipCollection];
	
	NSString* msg = @"\nFinding venue tips\nPlease wait...";
	[GraphicsUtilities displayActivityIndicatorWithMsg:msg];
	
	[ftvc updateWithUserLocation:loc 
					 andDelegate:self 
						tipLimit:[[MapAppSettings sharedSettings] foursquareTipLimit]];
}

/**
 * Handle a notification that the tip collection update has finished.
 *
 * @see  FoursquareTipCollectionDelegate
 */
- (void)handleTipCollectionUpdateDone {
	FoursquareTipCollection* fstc = [FoursquareTipCollection sharedTipCollection];
	NSMutableArray* tips = [NSMutableArray array];
	
	for (FoursquareTip* tip in [fstc allTips]) {
		FoursquareTipAnnotation* ann = [FoursquareTipAnnotation alloc];
		[ann initWithTip:tip];
		
		[tips addObject:ann];
	}
	
	if ([tips count] > 0) {
		[delegate displayFoursquareAnnotations:tips];
	} else {
		[GraphicsUtilities displayAlertWithTitle:@"No tips found." 
										 message:nil];
	}
	
	[GraphicsUtilities hideActivityIndicator];
}

/**
 * Helper method to view the venue specials on the map.
 *
 * @param loc  the location to search
 */
- (void)viewSpecialsAtLocation:(CLLocation*)loc {
	FoursquareVenueCollection* fsvc = [FoursquareVenueCollection sharedVenueCollection];
	
	NSString* msg = @"\nFinding venue specials\nPlease wait...";
	[GraphicsUtilities displayActivityIndicatorWithMsg:msg];
	
	[fsvc findSpecialsWithUserLocation:loc 
						   andDelegate:self 
						 specialsLimit:50];
}

/**
 * Handle a notification and return of venue specials from the initial search.
 *
 * @param specials  the venue specials found
 * @see             FoursquareVenueCollectionDelegate
 */
- (void)handleVenueSpecialsResults:(NSArray*)specials {
	NSMutableArray* venueSpecials = [NSMutableArray array];
	
	for (FoursquareVenue* venue in specials) {
		FoursquareSpecialAnnotation* ann = [FoursquareSpecialAnnotation alloc];
		[ann initWithVenue:venue];
		
		[venueSpecials addObject:ann];
	}
	
	if ([venueSpecials count] > 0) {
		[delegate displayFoursquareAnnotations:venueSpecials];
	} else {
		[GraphicsUtilities displayAlertWithTitle:@"No specials found." 
										 message:nil];
	}
	
	[GraphicsUtilities hideActivityIndicator];
}

/**
 * Helper method to find friend check-ins on the map.
 */
- (void)findFriendCheckIns {
	NSString* msg = @"\nFinding your friends\nPlease wait...";
	[GraphicsUtilities displayActivityIndicatorWithMsg:msg];
	
	
	[Foursquare recentFriendCheckinsNearLatitude:nil 
									   longitude:nil 
										callback:
	 ^(BOOL success, id response) {
		 if (success) {
			 NSMutableArray* friends = [NSMutableArray array];
			 NSDictionary* dict = [response objectForKey:@"checkins"];
			 //NSLog(@"%@", dict);
			 NSArray* friendsArray = [dict objectForKey:@"checkin"];
			 
			 for (NSDictionary* friend in friendsArray) {
				 // Get the attributes of the friend
				 NSString* date = [friend objectForKey:@"created"];
				 NSString* display = [friend objectForKey:@"display"];
				 NSString* shout = [friend objectForKey:@"shout"];
				 NSDictionary* user = [friend objectForKey:@"user"];
				 NSDictionary* venue = [friend objectForKey:@"venue"];
				 NSString* url = @"";
				 
				 if (user) {
					 url = [user objectForKey:@"photo"];
				 }
				 
				 // Get the attributes of the venue at which the friend is checked in
				 NSString* identifier = [venue objectForKey:@"id"];
				 NSString* name = [venue objectForKey:@"name"];
				 NSString* address = [venue objectForKey:@"address"];
				 NSString* city = [venue objectForKey:@"city"];
				 NSString* distance = [venue objectForKey:@"distance"];
				 NSString* category = [[venue objectForKey:@"primarycategory"] objectForKey:@"nodename"];
				 NSString* latitude = [venue objectForKey:@"geolat"];
				 NSString* longitude = [venue objectForKey:@"geolong"];
				 NSDictionary* specials = [venue objectForKey:@"specials"];
				 
				 FoursquareVenue* tempVenue = [[FoursquareVenue alloc] autorelease];
				 [tempVenue initWithID:identifier 
								  name:name
							   address:address
								  city:city 
							  distance:distance
							  category:category 
							  latitude:latitude 
							 longitude:longitude 
							  specials:specials];
				 
				 // Create the annotation to contain the friend information
				 FoursquareFriendAnnotation* ann = [FoursquareFriendAnnotation alloc];
				 [ann initWithVenue:tempVenue
							  shout:shout
						   imageURL:url 
							   date:date];
				 ann.title = display;
				 
				 if (latitude && longitude) {
					 [friends addObject:ann];
				 }
			 }
			 
			 if ([friends count] > 0) {
				 [delegate displayFoursquareAnnotations:friends];
			 } else {
				 [GraphicsUtilities displayAlertWithTitle:@"No friends found." 
												  message:nil];
			 }
		 }
		 
		 [GraphicsUtilities hideActivityIndicator];
		 [delegate handleFoursquareToolsDone];
	 }];
}

/** 
 * Helper method to clear the target actions on the Foursquare button.
 */
- (void)removeTargets {
	[foursquareButton removeTarget:self 
							action:@selector(requestLogin) 
				  forControlEvents:UIControlEventTouchUpInside];
	[foursquareButton removeTarget:self 
							action:@selector(requestCheckIn) 
				  forControlEvents:UIControlEventTouchUpInside];
}

/**
 * Get the Foursquare view for a given venue.
 *
 * @param theDelegate  the delegate handling Foursquare view events
 * @return             the Foursquare view for the venue
 */
- (UIView*)getFoursquareViewWithDelegate:(id<FoursquareViewDelegate>)theDelegate {
	FoursquareVenueCollection* fsvc = [FoursquareVenueCollection sharedVenueCollection];
	viewDelegate = theDelegate;
	
	double lat = [viewDelegate getVenueLocation].latitude;
	double lon = [viewDelegate getVenueLocation].longitude;
	CLLocation* loc = [[[CLLocation alloc] initWithLatitude:lat longitude:lon] autorelease];
	
	[fsvc updateWithUserLocation:loc 
					 andDelegate:self 
					  venueLimit:50 
					  identifier:VenueUpdateTypeView];
	
	NSLog(@" SIZE: %d", [fsvc size]);
	UIView* foursquareView = [[UIView alloc] autorelease];
	[foursquareView initWithFrame:CGRectMake(0, 0, VIEW_WIDTH, 50)];
	
	/*
	foursquareLabel = [[UILabel alloc] autorelease];
	[foursquareLabel initWithFrame:CGRectMake(0, 0, VIEW_WIDTH, 40)];
	foursquareLabel.backgroundColor = [UIColor clearColor];
	foursquareLabel.font = [UIFont boldSystemFontOfSize:15.0];
	foursquareLabel.textColor = [UIColor whiteColor];
	foursquareLabel.textAlignment = UITextAlignmentCenter;
	foursquareLabel.text = @"Loading Foursquare content...";
	[foursquareView addSubview:foursquareLabel];
	 */

	foursquareIndicator = [[UIActivityIndicatorView alloc] autorelease];
	[foursquareIndicator initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
	[foursquareIndicator setCenter:foursquareView.center];
	[foursquareIndicator startAnimating];
	[foursquareView addSubview:foursquareIndicator];
	
	foursquareButton = [UIButton buttonWithType:UIButtonTypeCustom];
	[self removeTargets];
		
	foursquareButton.frame = CGRectMake(0, 0, FOURSQUARE_BUTTON_WIDTH, FOURSQUARE_BUTTON_HEIGHT);
	foursquareButton.center = CGPointMake(VIEW_WIDTH/2, foursquareButton.center.y);
	[foursquareView addSubview:foursquareButton];
	
	return foursquareView;
}

/**
 * Handle a notification that the user Foursquare has successfully
 * logged into the Foursquare system
 *
 * @see  FoursquareLoginDelegate
 */
- (void)handleFoursquareLoginSuccess {
	FoursquareVenueCollection* fsvc = [FoursquareVenueCollection sharedVenueCollection];
	
	if ([viewDelegate getPossibleVenueNames]) {
		currentVenue = [fsvc findVenueWithNames:[viewDelegate getPossibleVenueNames]];
	}
	
	[self removeTargets];
	
	if (currentVenue) {
		[foursquareButton setBackgroundImage:[UIImage imageNamed:FOURSQUARE_CHECKIN_IMAGE] 
									forState:UIControlStateNormal];
		[foursquareButton addTarget:self 
							 action:@selector(requestCheckIn) 
				   forControlEvents:UIControlEventTouchUpInside];
	} else {
		[foursquareButton setBackgroundImage:[UIImage imageNamed:FOURSQUARE_NOVENUE_IMAGE] 
									forState:UIControlStateNormal];
	}
	
	foursquareButton.frame = CGRectMake(0, 0, FOURSQUARE_BUTTON_WIDTH, FOURSQUARE_BUTTON_HEIGHT);
	foursquareButton.center = CGPointMake(VIEW_WIDTH/2, foursquareButton.center.y);

}

/**
 * Helper method to request Foursquare login.
 */
- (void)requestLogin {
	[[FoursquareLogin sharedFoursquareLogin] showLoginWithDelegate:self];
}

/**
 * Request to check in at a given Foursquare venue.
 *
 * @param venue  the venue at which to check in
 */
- (void)requestCheckInAtVenue:(FoursquareVenue*)venue {
	if ([FoursquareLogin sharedFoursquareLogin].isLoggedIn) {
		currentVenue = venue;
		NSString* msg = [NSString stringWithFormat:@"Check in at %@ with shout:", 
						 currentVenue.venueName];
		checkInLabel.text = msg;
		
		[checkInPopup show];
	} else {
		[self requestLogin];
	}

}

/**
 * Helper method to request Foursquare venue check-in.
 */
- (void)requestCheckIn {
	[self requestCheckInAtVenue:currentVenue];
}

/**
 * Handle a call to dismiss the venue check-in pop-up.
 */
- (void)dismissCheckIn {
	checkInTextView.text = @"";
	checkInLabel.text = @"";
	[checkInTextView resignFirstResponder];
	[checkInPopup dismissWithClickedButtonIndex:0 animated:YES];
}

/**
 * Handle a call to attempt venue check-in.
 */
- (void)attemptCheckIn {
	if (!currentVenue) {
		return;
	}
	
	NSString* lat = [NSString stringWithFormat:@"%f", currentVenue.venueLocation.latitude];
	NSString* lon = [NSString stringWithFormat:@"%f", currentVenue.venueLocation.longitude];
	
	[Foursquare checkinAtVenueId:currentVenue.venueID 
					   venueName:currentVenue.venueName 
						   shout:[checkInTextView text] 
					 showFriends:YES
					   sendTweet:YES
					tellFacebook:YES
						latitude:lat 
					   longitude:lon
						callback:
	 ^(BOOL success, id response) {
		 if (success) {
			 NSDictionary* checkInDict = [response objectForKey:@"checkin"];
			 NSString* msg = [checkInDict objectForKey:@"message"];
			 
			 [GraphicsUtilities displayAlertWithTitle:msg message:nil];
		 } else {
			 [GraphicsUtilities displayAlertWithTitle:@"Failed to check in." 
											  message:nil];
		 }

	 }];
	
	[self dismissCheckIn];
}

/**
 * Helper method to show the location selector toolbar.
 */
- (void)activateLocSelectorMode {
	locSelectorModeOn = YES;
	searchLocation.latitude = 0;
	searchLocation.longitude = 0;
	
	// Create the toolbar buttons
	UIBarButtonItem* cancelButton = [[UIBarButtonItem alloc] autorelease];
	[cancelButton initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
									   target:self 
									   action:@selector(deactivateLocSelectorMode)];
	UIBarButtonItem* searchButton = [[UIBarButtonItem alloc] autorelease];
	[searchButton initWithTitle:@"Search" 
						  style:UIBarButtonItemStyleDone
						 target:self 
						 action:@selector(handleLocSelectorDone)];
	UIBarButtonItem* spacer = [[UIBarButtonItem alloc] autorelease];
	[spacer initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
								 target:nil
								 action:nil];
	
	// Add the buttons to the toolbar
	NSArray* buttons = [NSArray arrayWithObjects:cancelButton, spacer, searchButton, nil];
	[toolbar setItems:buttons animated:NO];
	
	[[delegate getViewController].view addSubview:toolbar];
	
	[GraphicsUtilities showPrompt:@"Tap to select a location to search." 
						   inView:[delegate getViewController].view 
						withColor:nil];
	
	// Animate the toolbar into visibility
	[UIView beginAnimations:nil context:@"toolbar"];
	[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
	[UIView setAnimationDuration:0.2];
	[toolbar setFrame:CGRectMake(0, VIEW_HEIGHT, VIEW_WIDTH, 44)];
	[UIView commitAnimations];
}

/**
 * Helper method to dismiss the location selector toolbar.
 */
- (void)deactivateLocSelectorMode {
	locSelectorModeOn = NO;
	[delegate removeTargetAnnotation];
	
	[GraphicsUtilities hidePromptAnimated:YES];
	
	// Animate the toolbar out of visibility
	[UIView beginAnimations:nil context:@"toolbar"];
	[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
	[UIView setAnimationDuration:0.3];
	[toolbar setFrame:CGRectMake(0, VIEW_HEIGHT+44, VIEW_WIDTH, 44)];
	[UIView commitAnimations];
}

/**
 * Initiate the search with the given search location.
 */
- (void)handleLocSelectorDone {
	if (searchLocation.latitude == 0 || searchLocation.longitude == 0) {
		[delegate removeTargetAnnotation];
		return;
	}
	
	[delegate removeTargetAnnotation];
	
	CLLocation* loc = [[CLLocation alloc] autorelease];
	[loc initWithLatitude:searchLocation.latitude 
				longitude:searchLocation.longitude];
	
	switch (searchType) {
		case FoursquareGeneralActionTypeVenues:
			[self viewVenuesAtLocation:loc];
			break;
		case FoursquareGeneralActionTypeTips:
			[self viewTipsAtLocation:loc];
			break;
		case FoursquareGeneralActionTypeSpecials:
			[self viewSpecialsAtLocation:loc];
			break;
	}
	
	[self deactivateLocSelectorMode];
}

/**
 * Respond to a touch event at the given point.
 *
 * @param touchPoint  the point at which a touch event was triggered
 * @see               TouchableWindowDelegate
 */
- (void)touchedAtPoint:(CGPoint)touchPoint {
	CGRect touchableFrame = CGRectMake(0, 0, VIEW_WIDTH, VIEW_HEIGHT);
	
	if (!CGRectContainsPoint(touchableFrame, touchPoint)) {
		return;
	}
	
	if (locSelectorModeOn) {
		searchLocation = [delegate coordFromPoint:touchPoint];
		[delegate removeTargetAnnotation];
		[delegate displayTargetAtLocation:searchLocation];
	}
}

/**
 * Limit the venue check-in shout text to 140 characters.
 */
- (BOOL)textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range 
 replacementText:(NSString*)text {
	if ([textView.text length] - range.length + text.length > 140) {
		return NO;
	}
	
	return YES;
}

/**
 * Display the appropriate content of the venue check-in pop-up when it appears.
 *
 * @see  UIAlertViewDelegate
 */
- (void)didPresentAlertView:(UIAlertView*)alertView {
	[checkInTextView becomeFirstResponder];
}

/**
 * Handle action sheet responses.
 *
 * @see  UIActionSheetDelegate
 */
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
	NSString* title = @"";
	NSString* msg = @"";
	
	if ([actionSheet tag] == FoursquareActionTypeGeneral) {
		switch (buttonIndex) {
			case FoursquareGeneralActionTypeLogin: // Sign in or sign out based on login status
				if ([actionSheet buttonTitleAtIndex:0] == @"Sign in") {
					[[FoursquareLogin sharedFoursquareLogin] showLoginWithDelegate:nil];
				} else {
					[[FoursquareLogin sharedFoursquareLogin] logout];
				}
				[delegate handleFoursquareToolsDone];
				return;
			case FoursquareGeneralActionTypeVenues: // View venues
				searchType = FoursquareGeneralActionTypeVenues;
				title = @"Select a location:";
				msg = @"Nearby venues";
				break;
			case FoursquareGeneralActionTypeTips: // View tips
				searchType = FoursquareGeneralActionTypeTips;
				title = @"Select a location:";
				msg = @"Nearby tips";
				break;
			case FoursquareGeneralActionTypeSpecials: // View specials
				searchType = FoursquareGeneralActionTypeSpecials;
				title = @"Select a location:";
				msg = @"Nearby specials";
				break;
			case FoursquareGeneralActionTypeFriends: // Find friends
				if ([actionSheet buttonTitleAtIndex:buttonIndex] != @"Cancel") {
					[self findFriendCheckIns];
				}
				[delegate handleFoursquareToolsDone];
				return;
			case FoursquareGeneralActionTypeCancel:
				[delegate handleFoursquareToolsDone];
				return;
		}
		
		// Proceed to another action sheet for location specification
		UIActionSheet* foursquareSearchActions = [UIActionSheet alloc];
		[foursquareSearchActions initWithTitle:title 
									  delegate:self
							 cancelButtonTitle:@"Cancel"               // 2 (index)
						destructiveButtonTitle:nil
							 otherButtonTitles:msg,                    // 0
		                                       @"Select own location", // 1
		                                       nil];
		[foursquareSearchActions setTag:FoursquareActionTypeSearch];
		[foursquareSearchActions showFromTabBar:parentTabBar];
		[foursquareSearchActions release];
		
		// Notify delegate
		[delegate handleFoursquareToolsDone];
	} else if ([actionSheet tag] == FoursquareActionTypeSearch) {
		if (buttonIndex == 0) { // Nearby
			switch (searchType) {
				case FoursquareGeneralActionTypeVenues: // View nearby venues
					[self viewVenuesAtLocation:[delegate getCurrentUserLocation]];
					break;
				case FoursquareGeneralActionTypeTips: // View nearby tips
					[self viewTipsAtLocation:[delegate getCurrentUserLocation]];
					break;
				case FoursquareGeneralActionTypeSpecials: // View nearby specials
					[self viewSpecialsAtLocation:[delegate getCurrentUserLocation]];
					break;
			}
		} else if (buttonIndex == 1) { // Select own location
			[self activateLocSelectorMode];
		}
		
		parentTabBar = nil;
	}
}

/**
 * Deallocate the Foursquare manager.
 */
- (void)dealloc {
	parentTabBar = nil;
	delegate = nil;
	viewDelegate = nil;
	currentVenue = nil;
	foursquareButton = nil;
	[foursquareIndicator release], foursquareIndicator = nil;
	//[foursquareLabel release], foursquareLabel = nil;
	[checkInLabel release], checkInLabel = nil;
	[checkInPopup release], checkInPopup = nil;
	[checkInTextView release], checkInTextView = nil;
	[toolbar release], toolbar = nil;
	[sharedFoursquareManager release], sharedFoursquareManager = nil;
    [super dealloc];
}

@end
